<template>
    <el-card class="box-card">
        <el-input v-model="state.config.url" placeholder="请输入地址模板..." clearable>
            <template #prepend>


                <el-popover :width="540" placement="bottom-start" trigger="click">
                    <template #reference>
                        <el-button :icon="Tools" />
                    </template>

                    <el-form :model="state.config" label-width="90px">

                        <el-form-item label="扫描超时">
                            <el-input-number v-model="state.config.timeout" :min="1" :max="10" controls-position="right" />
                        </el-form-item>

                        <el-row style="margin-bottom: 18px;">
                            <el-col :span="12">
                                <el-form-item label="扫描线程">
                                    <el-radio-group v-model="state.config.thread">
                                        <el-radio :label="0">单线程</el-radio>
                                        <el-radio :label="1">多线程</el-radio>
                                    </el-radio-group>
                                </el-form-item>
                            </el-col>
                            <el-col :span="10" v-if="state.config.thread">
                                <el-form-item label="扫描速度">
                                    <el-input-number v-model="state.config.speed" :min="0" controls-position="right" />
                                </el-form-item>
                            </el-col>
                        </el-row>

                        <el-form-item label="User-Agent">
                            <el-input v-model="state.config.agent" />
                        </el-form-item>

                        <el-form-item label="代理IP">
                            <el-input v-model="state.config.proxy" />
                        </el-form-item>

                        <el-form-item label="保留设置">
                            <el-checkbox v-model="state.config.high" label="仅保留高清" border />
                        </el-form-item>

                    </el-form>
                </el-popover>

            </template>
            <template #append>
                <el-button @click="startScan">{{ state.loading ? '暂停扫描' : '开始扫描' }}</el-button>
            </template>
        </el-input>

        <div class="progress">
            <el-progress :text-inside="true" :stroke-width="22" :percentage="state.progress" />
            <div class="progress-text">总计 {{ state.count }} 个地址，已扫描 {{ state.finish }} 个地址，扫描到 {{ state.valid }} 个有效频道！
            </div>
        </div>
        <div class="terminal">
            <div class="item" v-for="item in state.terminal" :key="item.id">
                <span class="time">{{ item.mtime }}</span>
                <span class="address" :class="item.status ? 'success' : 'error'">{{ item.url }}</span>
                <span class="state" :class="item.status ? 'success' : 'error'">{{ item.message }}</span>
                <span class="result" :class="item.status ? 'success' : 'error'">{{ item.status ? '有效' : '无效' }}</span>
            </div>
        </div>

        <div class="handle">
            <el-row :gutter="10">
                <el-col :span="5">
                    <el-select v-model="value" placeholder="Select" style="width: 100%;">
                        <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
                    </el-select>

                </el-col>
                <el-col :span="5"><el-button type="primary" plain>导入所选</el-button></el-col>
                <el-col :span="8">
                    <el-button type="success" plain @click="state.dialogVisible = true">导出结果</el-button>
                    <el-button type="info" plain @click="handleRate">获取码率</el-button>
                </el-col>
                <el-col :span="6" style="display: flex;justify-content: end;">
                    <el-button-group>
                        <el-button type="danger" plain @click="handleClearAddress">清空地址</el-button>
                        <el-button type="danger" plain @click="handleClearResult">清空结果</el-button>
                    </el-button-group></el-col>
            </el-row>
        </div>

        <el-table :data="state.tableData">
            <el-table-column prop="id" label="ID" width="60" />
            <el-table-column prop="name" label="名称" width="140">
                <template #default="scope">
                    {{ scope.row.name }}
                </template>
            </el-table-column>
            <el-table-column prop="url" label="地址" min-width="200" show-overflow-tooltip>
                <template #default="scope">
                    <el-text truncated @click='handleCopy(scope.row.url)' type="primary" style="cursor: pointer;">
                        {{ scope.row.url }}
                    </el-text>
                </template>
            </el-table-column>
            <el-table-column prop="address" label="预览" align="center">
                <template #default="scope">
                    <el-image :initial-index="scope.$index"
                        :src="'/api/php-admin/public/storage/cover/' + scope.row.id + '.jpg?_t=' + Date.parse(new Date()) + Math.round(Math.random() * 100)"
                        :preview-src-list="state.srcList" fit="cover" style="vertical-align: top;" hide-on-click-modal
                        preview-teleported>
                        <template #error>
                            <div class="image-slot">
                                <el-icon><icon-picture /></el-icon>
                            </div>
                        </template>
                    </el-image>
                </template>
            </el-table-column>
            <el-table-column prop="video_width" label="宽度" width="72" align="center" />
            <el-table-column prop="video_height" label="高度" width="72" align="center" />
            <el-table-column prop="video_encoded" label="视频编码" min-width="90" align="center" />
            <el-table-column prop="video_frame" label="帧率" min-width="72" align="center" show-overflow-tooltip="" />
            <el-table-column prop="video_rate" label="码率" width="66" align="center" />
            <el-table-column prop="audio_encoded" label="音频编码" width="80" align="center" />
            <el-table-column prop="audio_track" label="声道" width="80" align="center" />
            <el-table-column prop="audio_sampling_rate" label="采样率" min-width="70" align="center" />
        </el-table>

        <el-pagination class="pagination" v-model:page-size="state.rows" hide-on-single-page background
            layout="total, sizes,prev, pager, next, jumper" :total="state.total" @size-change="handleSizeChange"
            @current-change="handleCurrentChange" />

        <el-dialog v-model="state.dialogVisible" title="导出结果" width="50%">
            <el-input v-model="state.export" :rows="16" type="textarea" @click='handleCopy(state.export)' />
            <template #footer>
                <span class="dialog-footer">
                    <el-button type="primary" @click="handleGenerate">生成</el-button>
                </span>
            </template>
        </el-dialog>
    </el-card>
</template>

<script setup>
import { ref, reactive, onUnmounted } from 'vue'
import { useClipboard } from '@vueuse/core'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Picture as IconPicture, Tools } from '@element-plus/icons-vue'
import Request from '@/request'

const source = ref('Hello')
const { text, copy, copied, isSupported } = useClipboard({ source })

const state = reactive({
    terminal: [],
    tableData: [],
    srcList: [],
    loading: false,
    dialogVisible: false,
    empty: '暂无数据',
    export: '',
    count: 0,
    finish: 0,
    valid: 0,
    progress: 0,
    config: {
        url: '',
        timeout: 5,
        thread: 0,
        speed: 1000,
        agent: '',
        proxy: '',
        high: true
    },
    total: 0,
    rows: 20,
    page: 1
})

let interval = null;
let thread = null;

const config = localStorage.getItem('config')

if (config != null) {
    state.config = JSON.parse(config)
}

const startScan = () => {
    if (state.config.url.length < 1) {
        return ElMessage.warning('必须填写扫描模板！')
    }

    if (state.loading) {
        state.loading = false

        if (interval) clearInterval(interval)

        if (state.config.thread) {
            if (thread) clearInterval(thread)
        } else {
            Request.get('admin/scan/stop')
        }

        return ElMessage.warning('扫描暂停！')
    }

    state.loading = true

    localStorage.setItem('config', JSON.stringify(state.config))

    if (state.config.thread) {
        thread = setInterval(scan, state.config.speed)
    } else {
        scan()
    }

    interval = setInterval(getProgress, 1000)
}

const scan = () => {
    Request
        .post('admin/scan/scan?_t=' + Date.parse(new Date()) + Math.round(Math.random() * 100000), { config: state.config })
        .then(res => {
            if (res.code && interval) {
                clearInterval(interval)
            }
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const getProgress = () => {
    Request
        .get('admin/scan/progress?_t=' + Date.parse(new Date()) + Math.round(Math.random() * 100000))
        .then(res => {
            if (state.valid != res.datas.valid) {
                getDataList()
            }
            state.count = res.datas.count
            state.finish = res.datas.finish
            state.valid = res.datas.valid
            state.progress = res.datas.progress
            state.terminal = res.datas.data.reverse()

            if (state.progress == 100) {
                state.loading = false
                ElMessage.success('扫描已完成！')
                if (state.config.thread) {
                    if (thread) clearInterval(thread)
                }
                if (interval) clearInterval(interval)
            }

            if (res.datas.working && interval == null && state.progress != 100) {
                state.loading = true
                interval = setInterval(getProgress, 1000);
            }
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const handleSizeChange = (value) => {
    state.rows = value
    getDataList()
}

const handleCurrentChange = (value) => {
    state.page = value
    getDataList()
}

const handleCopy = (value) => {
    copy(value)
    ElMessage({
        grouping: true,
        message: copied ? '复制成功！' : '复制失败！',
        type: copied ? 'success' : 'error'
    })
}

const handleClearAddress = () => {
    ElMessageBox.confirm(
        '确定要清空扫描地址吗？',
        '提示',
        {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        }
    ).then(() => {
        handleClear('address')
    }).catch(() => {

    })
}

const handleClearResult = () => {
    ElMessageBox.confirm(
        '确定要清空扫描结果吗？',
        '提示',
        {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        }
    ).then(() => {
        handleClear('result')

    }).catch(() => {

    })
}

const handleClear = (field) => {
    Request
        .post('admin/scan/clear', { field: field })
        .then(res => {
            getProgress()
            ElMessage({
                grouping: true,
                message: res.message,
                type: res.code ? 'error' : 'success'
            })
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const handleRate = () => {
    Request
        .get('admin/scan/rate')
        .then(res => {

        })
        .catch((error) => {
            console.log('error', error)
        })
}

const handleGenerate = () => {
    state.export = ''
    Request
        .post('admin/scan/index', { page: 1, rows: 1000 })
        .then(res => {
            if (res.code) {
                state.export = res.message
            } else {
                let text = []
                res.datas.data.forEach(item => {
                    text.push(item.name + ',' + item.url)
                })

                state.export = text.join('\r\n')
            }
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const getDataList = () => {
    Request
        .post('admin/scan/index', { page: state.page, rows: state.rows })
        .then(res => {
            if (res.code) {
                state.empty = res.message
            } else {
                state.tableData = res.datas.data
                state.total = res.datas.total
                state.srcList = state.tableData.map(item => '/api/php-admin/public/storage/cover/' + item.id + '.jpg?_t=' + Date.parse(new Date()) + Math.round(Math.random() * 100))
            }
        })
        .catch((error) => {
            console.log('error', error)
        })
}


getProgress()

onUnmounted(() => {
    if (interval) clearInterval(interval)
})
</script>

<style scoped>
.progress {
    margin: 20px 0;
}

.terminal {
    margin-top: 20px;
    border-radius: 5px;
    background-color: black;
    padding: 20px;
    height: 220px;
    font-size: 12px;
}

.terminal .item {
    display: flex;
    justify-content: space-between;
    height: 22px;
    line-height: 22px;
    color: #C0C4CC;
}


.terminal .item .address {
    flex: 1;
    margin: 0 10px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.terminal .item .error {
    color: #F56C6C;
}

.terminal .item .success {
    color: #67C23A;
}


.terminal .item .state {
    margin-right: 10px;
}


.progress-text {
    margin-top: 10px;
    color: var(--el-color-info-light-2);
}

.handle {
    margin: 20px 0;
}

.image-slot {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    background: var(--el-fill-color-light);
    color: var(--el-text-color-secondary);
    font-size: 30px;
}

.image-slot .el-icon {
    font-size: 34px;
}
</style>